package com.ld.shieldsb.jgit;

import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.internal.storage.file.FileRepository;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;

import com.ld.shieldsb.common.core.collections.ListUtils;
import com.ld.shieldsb.common.core.util.date.DateUtil;
import com.ld.shieldsb.jgit.model.BranchCommitHashModel;
import com.ld.shieldsb.jgit.model.CommitHashModel;
import com.ld.shieldsb.jgit.model.GitCommitInfoModel;
import com.ld.shieldsb.jgit.model.LineDiff;

/**
 * git统计类
 * 
 * @ClassName GitStaticUtil
 * @author <a href="mailto:donggongai@126.com" target="_blank">吕凯</a>
 * @date 2021年6月7日 下午3:21:01
 *
 */
public class GitStaticUtil {
    /**
     * 根据项目路径和分支统计git日志
     * 
     * @Title commitResolver
     * @author 吕凯
     * @date 2021年6月7日 下午3:26:02
     * @param localPath
     * @param branchName
     * @return
     * @throws IOException
     * @throws GitAPIException
     *             List<GitCount>
     */
    public static List<GitCommitInfoModel> commitResolver(String localPath, String projectName, String branchName)
            throws IOException, GitAPIException {
        // 定义数据及变量
        List<GitCommitInfoModel> listGitCount = new ArrayList<>();
        List<BranchCommitHashModel> list = commitList(localPath, branchName);
        for (BranchCommitHashModel branchCommit : list) {
            String branch = branchCommit.getBranch();
            branch = branch.substring(branch.lastIndexOf("/") + 1, branch.length());
            List<CommitHashModel> mapList = branchCommit.getList();
            for (CommitHashModel map : mapList) {
                RevCommit revCommit = map.getCommitHash();
                List<RevCommit> listParent = map.getCommitParentHash();

                // 版本比较获取增删行数
                LineDiff lineDiff = getLineChange(revCommit, listParent, localPath);
                int addLine = lineDiff.getAddLine();
                int removeLine = lineDiff.getRemoveLine();

                // 获取当前commit信息
                String commitTime = DateUtil.getDateTimeString(revCommit.getAuthorIdent().getWhen());
                String authorName = revCommit.getAuthorIdent().getName();
                String commitMessage = revCommit.getFullMessage();
                String email = revCommit.getAuthorIdent().getEmailAddress();

                // 获取设置值放入对象中
                GitCommitInfoModel gitCount = new GitCommitInfoModel();
                gitCount.setId(ObjectId.toString(revCommit.getId())); // 需要转换，直接取出来是对象
                gitCount.setEmail(email);
                gitCount.setAuthor(authorName);

                gitCount.setProject(projectName);
                List<String> branchList = ListUtils.newArrayList();
                branchList.add(branch);
                gitCount.setBranch(branchList);

                gitCount.setCommitTime(commitTime);
                gitCount.setCommitMessage(commitMessage);
                gitCount.setAddLine(addLine);
                gitCount.setRemoveLine(removeLine);
                if (commitMessage.contains("Merge")) {
                    gitCount.setIsMerge(1);
                } else {
                    gitCount.setIsMerge(0);
                }
                listGitCount.add(gitCount);
            }
        }

        return listGitCount;
    }

    /**
     * 
     * 传入父子commit对象返回新增，删除行数
     * 
     * @Title getLineChange
     * @author 吕凯
     * @date 2021年6月7日 下午3:26:49
     * @param revCommit
     * @param listParent
     * @param localPath
     * @return
     * @throws IOException
     * @throws GitAPIException
     *             Map<String,Object>
     */
    public static LineDiff getLineChange(RevCommit revCommit, List<RevCommit> listParent, String localPath)
            throws IOException, GitAPIException {
        // 定义数据及变量
        List<RevCommit> commitList = new ArrayList<>();
        LineDiff linediff = new LineDiff();
        int addLine = 0;
        int removeLine = 0;
        if (listParent.isEmpty()) { // 父版本提交记录为空
            addLine = GitUtil.getAllFileLines(revCommit, localPath);
        } else {
            for (RevCommit revCommitParent : listParent) {
                // 集合中只保存两个版本值，进行比较，统计出新增和删除行数
                if (commitList.size() == 2) {
                    commitList.clear();
                }
                // 往集合中添加提交版本
                commitList.add(revCommit);
                commitList.add(revCommitParent);
                // 控制版本，两个相邻版本进行文件对比
                LineDiff diff = GitUtil.gitDiff(commitList, localPath);
                addLine = addLine + diff.getAddLine();
                removeLine = removeLine + diff.getRemoveLine();
            }
        }
        linediff.setAddLine(addLine);
        linediff.setRemoveLine(removeLine);
        return linediff;
    }

    /**
     * 提取一个项目所有的提交记录，不包含重复的commit记录
     * 
     * @Title commitList
     * @author 吕凯
     * @date 2021年6月7日 下午3:27:05
     * @param localPath
     * @param branchMain
     * @return
     * @throws IOException
     * @throws GitAPIException
     *             List<Map<String,Object>>
     */
    public static List<BranchCommitHashModel> commitList(String localPath, String branchMain) throws IOException, GitAPIException {
        // 定义集合
        Set<CommitHashModel> commitMapSet = new LinkedHashSet<>(); // 所有的提交记录不区分分支 [{"commitHash":"xxx","commitParentHash":[]},……]
        List<BranchCommitHashModel> resultMapList = new ArrayList<>(); // 最终返回结果[{"branch":"分支[如：refs/remotes/origin/master]","list":[{"commitHash":"xxx","commitParentHash":[]},……]},{},……]
        List<CommitHashModel> nowCommitMapList = new ArrayList<>(); // 当前分支处理完后的提交记录
        List<CommitHashModel> prevCommitMapList = new ArrayList<>(); // 上一个分支处理完后的提交记录
        // 获取所有远程分支
        List<String> branchList = GitUtil.getAllBranch(localPath);
        branchList.remove(branchMain);
        branchList.add(0, branchMain); // 主分支添加到第一个的位置
        // 循环遍历分支
        for (int i = 0; i < branchList.size(); i++) {
            String branch = branchList.get(i); // 分支名称
            // fetch
            // GitUtil.fetchBranch(localPath);
            // 切换分支
            // GitUtil.switchBranch(localPath,branch);
            // pull代码
            // GitUtil.gitPull(username,password,localPath,branch);
            // 获取git记录

            try (Git git = new Git(new FileRepository(localPath + "/.git"));
                    Repository repository = git.getRepository();
                    RevWalk revWalk = new RevWalk(repository);) {

                ObjectId commitId = repository.resolve(branch);
                if (commitId != null) {

                    revWalk.markStart(revWalk.parseCommit(commitId));
                    // 类型转化为commit对象进行循环提取数据
                    for (RevCommit revCommit : revWalk) {
                        CommitHashModel map = new CommitHashModel();
                        List<RevCommit> listParent = new ArrayList<>(); // 父版本提交记录
                        // 当前版本哈希值
                        map.setCommitHash(revCommit);
                        // 父版本哈希值
                        // 当前版本merge过来父版本哈希值有几个
                        int parentNum = revCommit.getParentCount();
                        for (int j = 0; j < parentNum; j++) {
                            // 当前版本父类哈希
                            RevCommit revCommitParent = revCommit.getParent(j);
                            listParent.add(revCommitParent);
                        }
                        map.setCommitParentHash(listParent); // 父版本提交
                        commitMapSet.add(map);
                    }
                    // 提取这个分支下不重复的commit对象
                    BranchCommitHashModel map2 = new BranchCommitHashModel();
                    List<CommitHashModel> newList1 = new ArrayList<>(commitMapSet);
                    List<CommitHashModel> newList2 = new ArrayList<>(commitMapSet);
                    if (nowCommitMapList.isEmpty()) { // 初次执行
                        nowCommitMapList = newList1;
                        prevCommitMapList = newList2;
                        map2.setBranch(branch);
                        map2.setList(nowCommitMapList);
                        resultMapList.add(map2);
                    } else {
                        nowCommitMapList = newList1; // 添加了当前分支结果的list
                        if (prevCommitMapList.size() != nowCommitMapList.size()) { // 与上一个分支处理后的结果比较，如果不相等说明当前分支有内容，则继续进行处理
                            // 因为存在分支合并，所以有重复的提交记录
                            if (prevCommitMapList.size() > nowCommitMapList.size()) {
                                // 移除相同数据
                                prevCommitMapList.removeAll(nowCommitMapList);
                                map2.setBranch(branch);
                                map2.setList(prevCommitMapList);
                                resultMapList.add(map2);
                            } else if (nowCommitMapList.size() > prevCommitMapList.size()) {
                                // 移除相同数据
                                nowCommitMapList.removeAll(prevCommitMapList);
                                map2.setBranch(branch);
                                map2.setList(nowCommitMapList);
                                resultMapList.add(map2);
                            }

                        }
                        prevCommitMapList = newList2; // 把当前分支处理后的结果赋值给
                    }
                }
            }

        }
        return resultMapList;
    }

}
